package com.ks.demo.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author：kangsen
 * @Date：2022/9/29/0029 21:48
 * @Versiion：1.0
 * @Desc: 死信交换机配置
 */
@Configuration
@Slf4j
public class DeadRabbitConfig {

    /**
     * 正常队列
     * @return
     */
    @Bean
    public Queue normalQueue(){
        Map<String,Object> map = new HashMap<>();
        //message在队列queue的最大存活时间为5s
        map.put("x-message-ttl", 5000);
        //设置死信交换机
        map.put("x-dead-letter-exchange","deadExchange");
        //设置死信交换机的路由键
        map.put("x-dead-letter-routing-key", "dead");
        return new Queue("normalQueue",true,false,false,map);
    }

    /**
     * 死信队列
     *
     * 1.消息被拒绝，并且设置为requeue参数为false
     * 消息确认可以让 RabbitMQ 知道消费者已经接受并处理完消息。但是如果消息本身或者消息的处理过程出现问题怎么办？需要一种机制，
     * 通知RabbitMQ，这个消息，我无法处理，请让别的消费者处理。这里就有两种机制，Reject 和 Nack。
     *
     *
     * 2.消息过期（默认情况下Rabbit中的消息不过期，但是可以设置队列的过期时间和消息的过期时间以上达到消息过期的效果）
     * ttl时间过了 消息会被投递到私信交换机接着消息会被路由到死信队列中   被监听死信队列的消费者消费
     *
     *
     *
     * 3.队列达到最大长度（一般当设置了最大队列长度或大小并达到最大值时）
     *
     * @return
     */
    @Bean
    public Queue deadQueue(){
        return new Queue("deadQueue",true);
    }


    @Bean
    public DirectExchange normalExchange(){
        return new DirectExchange("normalExchange");
    }

    @Bean
    public DirectExchange deadExchange(){
        return new DirectExchange("deadExchange");
    }

    /**
     * 绑定正常交换机和正常队列
     * @return
     */
    @Bean
    public Binding normalBinding(){
        return BindingBuilder.bind(normalQueue()).to(normalExchange()).with("normal");
    }

    /**
     * 绑定死信交换机和死信队列
     * @return
     */
    @Bean
    public Binding deadBinding(){
        return BindingBuilder.bind(deadQueue()).to(deadExchange()).with("dead");
    }
}
